package wci.frontend.c.tokens;


import wci.frontend.Source;
import wci.frontend.c.CToken;
import static wci.frontend.Source.EOL;
import static wci.frontend.c.CTokenType.CHARACTER;
import static wci.frontend.c.CTokenType.ERROR;
import static wci.frontend.c.CErrorCode.*;

/**
 * CCharacterToken
 * 
 * C Character Tokens.
 * 
 * @author Gregory Marshall
 *	
 */
public class CCharacterToken extends CToken
{

	public CCharacterToken(Source source)
		throws Exception
	{
		super(source);
	}
	
	/**
	 * Extracts a character token from the source
	 * @throws Exception if invalid character or escape sequence
	 */
	protected void extract()
		throws Exception
	{
		StringBuilder textBuffer = new StringBuilder();
	    char currentChar = currentChar();
	    boolean invalidEscapeSequence = false;
	    
	    if (currentChar == '\'')
	    {
	    	currentChar = nextChar();
	    	if (currentChar == '\\')
	    	{
	    		currentChar = nextChar();
	    		switch(currentChar)
            	{
            	case 'b': // backspace
            		textBuffer.append("\\b");
                	break;
            	case 'n': // newline
            		textBuffer.append("\\n");
                	break;
            	case 'r': // carriage return
            		textBuffer.append("\\r");
                	break;
            	case '\\':
            		textBuffer.append("\\\\");
                	break;
            	case 't':
            		textBuffer.append("\\t");
                	break;
            	case '\'':
            		textBuffer.append("\\'");
                	break;
            	case '\"':
            		textBuffer.append("\\\"");
                	break;
                default:
                	invalidEscapeSequence = true;
                	textBuffer.append("\\" + nextChar());
            	}
	    	}
	    	else
	    		textBuffer.append(currentChar);
	    }
	    
	    //Checks if it is an invalid character (too many characters)
	    if(peekChar() != '\'')
    	{
	    	nextChar();
    		do
    		{
    			textBuffer.append(currentChar());
    			nextChar();
    		}
    		while (currentChar() != '\'');

			type = ERROR;
			value = INVALID_CHARACTER;
    	}
    	
	    //If invalid escape sequence sets error
    	else if (invalidEscapeSequence)
    	{
    		type = ERROR;
    		value = UNKNOWN_ESCAPE_SEQUENCE;
    	}
    	
	    //If the character is valid, sets type and consumes the char
    	else if (peekChar() == '\'')
    	{
    		nextChar();
    	    type = CHARACTER;
    	}
	    

		text = textBuffer.toString();
	    nextChar();
	}
}